﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Lucene.Net.Store;
using System.Collections;
using Lucene.Net.Search;
using Lucene.Net.QueryParsers;
using Lucene.Net.Analysis.Standard;
using Lucene.Net.Index;

namespace JSC.Portal.Search
{
    public class SearchIndexQuery
    {
		private Directory _indexDirectory;

		/// <summary>
		/// Default constructor.
		/// <param name="physicalIndexDir">The physical directory where the search index resides.</param>
		/// </summary>
        public SearchIndexQuery(string physicalIndexDir)
		{
			_indexDirectory = FSDirectory.GetDirectory(physicalIndexDir, false);
		}

		/// <summary>
		/// Searches the index.
		/// </summary>
		/// <param name="queryText"></param>
		/// <param name="keywordFilter">A Hashtable where the key is the fieldname of the keyword and 
		/// the value the keyword itself.</param>
		/// <param name="pageIndex"></param>
		/// <param name="pageSize"></param>
		/// <returns></returns>
		public SearchResultCollection Find(string queryText, Hashtable keywordFilter, int pageIndex, int pageSize)
		{
			long startTicks = DateTime.Now.Ticks;

			Query query = MultiFieldQueryParser.Parse(
                queryText, 
                new string[]{"title", "contents"},
                new BooleanClause.Occur[] { BooleanClause.Occur.SHOULD, BooleanClause.Occur.SHOULD},
                new StandardAnalyzer());
			IndexSearcher searcher = new IndexSearcher(_indexDirectory);
			Hits hits;
			if (keywordFilter != null && keywordFilter.Count > 0)
			{
				QueryFilter qf = BuildQueryFilterFromKeywordFilter(keywordFilter);
				hits = searcher.Search(query, qf);
			}
			else
			{
				hits = searcher.Search(query);
			}
			int start = pageIndex * pageSize;
			int end = (pageIndex + 1) * pageSize;
			if (hits.Length() <= end)
			{
				end = hits.Length();
			}
			SearchResultCollection results = new SearchResultCollection();
			results.TotalCount = hits.Length();
			results.PageIndex = pageIndex;
			
			for (int i = start; i < end; i++)
			{
				SearchResult result = new SearchResult();
				result.Name = hits.Doc(i).Get("name");
				result.Description = hits.Doc(i).Get("description");
				result.Author = hits.Doc(i).Get("author");
				result.ModuleType = hits.Doc(i).Get("moduletype");
				result.Path = hits.Doc(i).Get("path");
				result.Category = hits.Doc(i).Get("category");
				result.DateCreated = DateTime.Parse((hits.Doc(i).Get("datecreated")));
				result.Score = hits.Score(i);
				result.Boost = hits.Doc(i).GetBoost();
				result.SectionId = Int32.Parse(hits.Doc(i).Get("sectionid"));
				results.Add(result);
			}
			searcher.Close();
			results.ExecutionTime = DateTime.Now.Ticks - startTicks;

			return results;
		}

		private QueryFilter BuildQueryFilterFromKeywordFilter(Hashtable keywordFilter)
		{
			BooleanQuery bQuery = new BooleanQuery();
			foreach(DictionaryEntry keywordFilterTerm in keywordFilter)
			{
				string field = keywordFilterTerm.Key.ToString();
				string keyword = keywordFilterTerm.Value.ToString();
				bQuery.Add(new TermQuery(new Term(field, keyword)), BooleanClause.Occur.MUST);
			}

			return new QueryFilter(bQuery);
		}
	}
}
